/**
 * @author jprieur
 */
package mygui;

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.jfree.data.xy.*;

import utils.Debug;
import java.util.*;

public class ResultContentHandler extends DefaultHandler
{
    private static enum Phase { undefined, configuration, objects, measures; }
    private HashMap<String,ResultObject> _objects;
    private ResultObject _current;
    private ResultProbe _probe;
    private Phase _phase;
    private XYSeries _serie;
    HashMap<Double,String> _trace;
    private String _namespace; // TODO : manage a complete namespace

    public ResultContentHandler(HashMap<String,ResultObject> objects)
    {
	_objects = objects;
	_phase = Phase.undefined;
    }

    public void startDocument() throws SAXException {
    }

    public void startElement(String uri, 
			     String localName, 
			     String qName, 
			     Attributes att)
	throws SAXException
    {
	if(qName.equals("configuration")){
	    _phase = Phase.configuration;
	    return;
	}else if(qName.equals("simulation")){
	    _current = new ResultObject(ResultObject.Type.simulation, 
					"00000000-0000-0000-0000-000000000000");
	    _current.setName(att.getValue("name"));
	    _objects.put(_current.getUUID(), _current);
	    for(int i = 0;i<att.getLength();i++){
		_current.getProperties().put(
					     att.getQName(i),
					     att.getValue(i));
	    }
	    return;
	}else if(qName.equals("objects")){
	    _phase = Phase.objects;
	    return;
	}else if(qName.equals("measures")){
	    _phase = Phase.measures;
	    return;
	}

	switch(_phase){
	case configuration:
	    break;
	case objects:
	    if(qName.equals("base")){
		_current = new ResultObject(ResultObject.Type.base_station,
					    att.getValue("uuid"));
		_current.setName(att.getValue("name"));
		_objects.put(_current.getUUID(), _current);
	    
	    }else if(qName.equals("mobile")){
		_current = new ResultObject(ResultObject.Type.mobile_station,
					    att.getValue("uuid"));
		_current.setName(att.getValue("name"));
		_objects.put(_current.getUUID(), _current);
	    
	    }else if(qName.equals("sink")){
		_current = new ResultObject(ResultObject.Type.sink,
					    att.getValue("uuid"));
		_current.setName(att.getValue("name"));
		_objects.put(_current.getUUID(), _current);
	    
	    }else if(qName.equals("sensornetwork")){
		_current = new ResultObject(ResultObject.Type.sensor_network,
					    att.getValue("uuid"));
		_current.setName(att.getValue("name"));
		_objects.put(_current.getUUID(), _current);

	    }else if(qName.equals("obstacle")){
		_current = new ResultObject(ResultObject.Type.sink,
					    att.getValue("uuid"));
		_current.setName(att.getValue("name"));
		_objects.put(_current.getUUID(), _current);

	    }else{
		fillAll(_current.getProperties(), att, qName);
	    }

	    for(int i = 0;i<att.getLength();i++){
		_current.getProperties().put(
					     att.getQName(i),
					     att.getValue(i));
	    }
	    break;
	case measures:
	    if(qName.equals("probe_result")){
		_probe = new ResultProbe(att.getValue("property"),
					 att.getValue("uuid_ref"));

		if(att.getValue("property").equals("ProbeMovePosition")){
		    _probe.getSeriesCollection().addSeries(new XYSeries("X"));
		    _probe.getSeriesCollection().addSeries(new XYSeries("Y"));
		}else if(att.getValue("property").equals("ProbeComReachableNeighbors") ||
			 att.getValue("property").equals("ProbeComCarrierNeighbors") ||
			 att.getValue("property").equals("ProbeDataSink") ||
			 att.getValue("property").equals("ProbeDirectedDiffusion")){
		    _probe.setTraceable(false);
		    _trace = new HashMap<Double,String>();
		}else{
		    _probe.getSeriesCollection().addSeries(new XYSeries(_probe.getType()));

		    System.out.println(att.getValue("property"));
		}
		
	    }else if(qName.equals("data")){
		XYSeriesCollection collection = _probe.getSeriesCollection();
		Double time = new Double(att.getValue("time"));

		if(!_probe.isTraceable()){
		    _trace.put(time,(String)att.getValue("value"));
		}else{
		    if(_probe.getType().equals("ProbeMovePosition")){
			String[] s = ((String)att.getValue("value")).split(";");
			Double x = Double.parseDouble(s[0]);
			Double y = Double.parseDouble(s[1]);
			collection.getSeries(0).add(time,x);
			collection.getSeries(1).add(time,y);
		    }else{
			collection.getSeries(0).add(time.doubleValue(),(new Double(att.getValue("value"))).doubleValue());
		    }
		}
	    }
	    break;
	default:
	    //	    Debug.getConfigLogger().warning("unhandled element : " + qName);
	}
    }

    public void characters(char[] ch, int start, int length) 
	throws SAXException
    {
    }

    public void endElement(String uri, String localName, String qName)
	throws SAXException
    {
	if(qName.equals("configuration") ||
	   qName.equals("base") ||
	   qName.equals("mobile") ||
	   qName.equals("sink") ||
	   qName.equals("sensornetwork") ||
	   qName.equals("obstacle")){
	    _current = null;
	}else if(qName.equals("probe_result")){
	    ResultObject object = _objects.get(_probe.getObjectUUID());
	    ArrayList<ResultProbe> probes = object.getProbes();
	    if(!_probe.isTraceable()){
		_probe.setTrace(_trace);
	    	_trace.clear();
	    }
	    probes.add(_probe);
	}
    }

    public void endDocument()
	throws SAXException
    {
    }

    public void error(SAXParseException e) throws SAXParseException
    {
	throw e;
    }

    private void fillAll(HashMap<String,String> destination, 
			 Attributes source, String namespace)
    {
	for(int i=0;i < source.getLength();i++){
	    destination.put(namespace + "." + source.getQName(i), 
			    source.getValue(i));
	}
    }
			 

}